/**
 * 
 */
package org.whuims.io;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.whusim.entity.Passage;
import org.whusim.utils.Config;
import org.whusim.utils.UnicodeUtils;

/**
 * 用于读取ReuterDump文件的类，依赖于guide文件位置信息表和dump文件（将解析过的文档存在一处，使用RandomAccessFile�?
 * <ul>
 * <li>位置信息消耗内存700000×12byte~1M内存</li>
 * <li>维持RandomAccessFile内存映射1200kb</li>
 * <li></li>
 * </ul>
 * 
 * @author ChengQikai
 */
public class ReuterDumpReader {
	static byte[] locations = null;
	private static BufferedInputStream in = null;
	private static RandomAccessFile raf = null;
	static {
		try {
			File mapBinFile = new File(Config.getProp("sentbased_dumpfile_guide_path"));
			// System.out.println(mapBinFile.getAbsolutePath());
			locations = new byte[(int) mapBinFile.length()];
			in = new BufferedInputStream(new FileInputStream(mapBinFile));
			in.read(locations);
			in.close();
			System.out.println("load dumpFile_guide finished...");
			raf = new RandomAccessFile(Config.getProp("sentbased_dumpfile_path"), "r");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 文件使用完毕后需要手动关闭。
	 * 
	 * @throws IOException
	 */
	public static void close() throws IOException {
		locations = null;
		raf.close();
	}

	/**
	 * <p>根据docNO读取文件并加工成Passage返回。</p>
	 * <p>passage仅有三个字段，docNO、title、SentenceList</p>
	 * @param docNO 文档编号，读取文件的依据
	 * @return 返回对应文档的Passage对象
	 * @throws IOException 
	 */
	public static Passage readPassage(int docNO) throws IOException {
		String rawText = read(docNO);
		String[] array = rawText.split("\r\n");
		Passage passage = new Passage();
		List<String> sentenceList = new ArrayList<String>();
		for (int i = 2; i < array.length; i++) {
			sentenceList.add(array[i]);
			// System.out.println("句子"+(i-1)+"\t"+array[i]);
		}
		passage.setDocNO(docNO + "");
		passage.setTitle(array[0]);
		// System.out.println("这是title:"+array[0]);
		passage.setHeadline(array[1]);
		// System.out.println("这是headline："+array[1]);
		passage.setSentenceList(sentenceList);
		rawText = null;
		return passage;
	}

	/**
	 * 根据输入的docNO，返回对应的title和sent组成的字符串
	 * docNO如果小于86968，将会出错,这个错误将不被处理，调用时务须注意.
	 * @param docNO
	 * @return
	 * @throws IOException
	 */
	static Map<String, String> textMap = new HashMap<String, String>();

	public static String read(int docNO) throws IOException {
		if (textMap.containsKey(docNO + "")) {
			return textMap.get(docNO + "");
		}
		int offset = checkOffset(docNO);
		byte[] offsetBytes = new byte[8];
		byte[] lengthBytes = new byte[4];
		int num = 0;
		int i = offset;
		for (; num < 8; i++) {
			offsetBytes[num++] = locations[i];
		}
		num = 0;
		i = offset + 8;
		for (; num < 4; i++) {
			lengthBytes[num++] = locations[i];
		}
		long startPointer = UnicodeUtils.bytes2Long(offsetBytes);
		int length = UnicodeUtils.bytes2int(lengthBytes);
		raf.seek(startPointer);
		byte[] bytes = new byte[length];
		raf.read(bytes);
		String content = new String(bytes);
		if (textMap.size() < 6000) {
			textMap.put(docNO + "", content);
		}
		return content;
	}

	/**
	 * @param docNO
	 * @return
	 */
	private static int checkOffset(int docNO) {
		int offset = docNO - 86968;
		offset = 12 * offset;
		return offset;
	}

	public static void main(String[] args) {
		try {
			// System.out.println(ReuterDumpReader.read(286968));
			Passage passage = ReuterDumpReader.readPassage(86998);
			System.out.println(passage.getTitle());
			System.out.println(passage.getSentenceList().size());
			System.out.println(passage.getHeadline());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
